const cron = require('node-cron');
const fs = require('fs');
const path = require('path');
const BaiduHotCrawler = require('./crawler');

/**
 * 百度热搜爬虫调度器
 */
class CrawlerScheduler {
  constructor() {
    this.crawler = new BaiduHotCrawler();
    this.task = null;
    this.configPath = path.join(process.cwd(), 'config.json');
    this.config = this.loadConfig();
  }

  /**
   * 加载配置文件
   */
  loadConfig() {
    try {
      if (fs.existsSync(this.configPath)) {
        const config = JSON.parse(fs.readFileSync(this.configPath, 'utf8'));
        return config;
      }
    } catch (error) {
      console.error('加载配置文件失败:', error);
    }
    
    // 默认配置
    return {
      cronExpression: '*/3 * * * *', // 每3分钟执行一次
      saveHistoryDays: 7, // 保存历史数据的天数
      autoStartSchedule: true // 是否在启动时自动开始定时任务
    };
  }

  /**
   * 保存配置到文件
   */
  saveConfig() {
    try {
      fs.writeFileSync(this.configPath, JSON.stringify(this.config, null, 2), 'utf8');
      console.log('配置已保存');
    } catch (error) {
      console.error('保存配置文件失败:', error);
    }
  }

  /**
   * 更新配置
   * @param {Object} newConfig 新配置
   */
  updateConfig(newConfig) {
    this.config = { ...this.config, ...newConfig };
    this.saveConfig();
    
    // 如果更新了定时表达式，则重启定时任务
    if (newConfig.cronExpression && this.task) {
      this.stopSchedule();
      this.startSchedule(newConfig.cronExpression);
    }
    
    return this.config;
  }

  /**
   * 执行爬取任务
   */
  async runCrawlTask() {
    console.log('开始执行定时爬取任务...');
    
    try {
      const result = await this.crawler.crawl();
      
      if (result.success) {
        console.log(`成功爬取 ${result.data.length} 条热搜`);
        
        // 清理过期数据
        this.cleanupOldData();
      } else {
        console.error('热搜爬取失败:', result.message);
      }
      
      return result;
    } catch (error) {
      console.error('定时爬取任务失败:', error);
      return {
        success: false,
        message: error.message,
        timestamp: new Date().toISOString()
      };
    }
  }

  /**
   * 手动触发爬取任务
   */
  async manualCrawl() {
    console.log('手动触发爬取百度热搜...');
    
    try {
      const result = await this.crawler.crawl();
      return result;
    } catch (error) {
      console.error('手动爬取百度热搜失败:', error);
      return {
        success: false,
        message: error.message,
        timestamp: new Date().toISOString()
      };
    }
  }

  /**
   * 清理过期数据
   */
  cleanupOldData() {
    try {
      const dataDir = path.join(process.cwd(), 'data');
      if (!fs.existsSync(dataDir)) return;
      
      // 获取文件夹列表
      const dateDirs = fs.readdirSync(dataDir)
        .filter(item => {
          const dirPath = path.join(dataDir, item);
          return fs.statSync(dirPath).isDirectory() && /^\d{4}-\d{2}-\d{2}$/.test(item);
        })
        .sort();
      
      // 保留最近N天的数据
      const saveHistoryDays = this.config.saveHistoryDays || 7;
      
      // 如果日期文件夹数量超过保留天数，删除旧的文件夹
      if (dateDirs.length > saveHistoryDays) {
        const dirsToDelete = dateDirs.slice(0, dateDirs.length - saveHistoryDays);
        
        for (const dir of dirsToDelete) {
          const dirPath = path.join(dataDir, dir);
          fs.rmSync(dirPath, { recursive: true, force: true });
          console.log(`已删除过期数据目录: ${dirPath}`);
        }
      }
    } catch (error) {
      console.error('清理过期数据失败:', error);
    }
  }

  /**
   * 获取所有保存的历史数据
   */
  getHistoryData() {
    try {
      const dataDir = path.join(process.cwd(), 'data');
      if (!fs.existsSync(dataDir)) return [];
      
      // 获取日期文件夹列表
      const dateDirs = fs.readdirSync(dataDir)
        .filter(item => {
          const dirPath = path.join(dataDir, item);
          return fs.statSync(dirPath).isDirectory() && /^\d{4}-\d{2}-\d{2}$/.test(item);
        })
        .sort((a, b) => b.localeCompare(a)); // 降序排列，最新的在前面
      
      const historyData = [];
      
      for (const dateDir of dateDirs) {
        const dirPath = path.join(dataDir, dateDir);
        
        // 获取该日期下的所有JSON文件
        const jsonFiles = fs.readdirSync(dirPath)
          .filter(file => file.endsWith('.json'))
          .sort((a, b) => b.localeCompare(a)); // 降序排列，最新的在前面
        
        // 添加每个时间点的数据
        jsonFiles.forEach(file => {
          historyData.push({
            date: dateDir,
            time: file.replace('baidu_hot_', '').replace('.json', ''),
            filePath: path.join(dirPath, file)
          });
        });
      }
      
      return historyData;
    } catch (error) {
      console.error('获取历史数据失败:', error);
      return [];
    }
  }

  /**
   * 获取最新的热搜数据
   */
  getLatestHotSearch() {
    try {
      const latestFilePath = path.join(process.cwd(), 'data', 'latest_hot.json');
      
      if (fs.existsSync(latestFilePath)) {
        const data = JSON.parse(fs.readFileSync(latestFilePath, 'utf8'));
        return { success: true, data };
      } else {
        return { success: false, message: '没有找到最新热搜数据' };
      }
    } catch (error) {
      console.error('获取最新热搜数据失败:', error);
      return { success: false, message: error.message };
    }
  }

  /**
   * 启动定时任务
   * @param {string} cronExpression cron表达式，默认为每3分钟执行一次
   */
  startSchedule(cronExpression) {
    if (this.task) {
      console.log('定时任务已在运行中');
      return false;
    }
    
    // 使用配置中的表达式或传入的表达式
    const cronExp = cronExpression || this.config.cronExpression || '*/3 * * * *';
    
    this.task = cron.schedule(cronExp, () => {
      this.runCrawlTask();
    });
    
    console.log(`定时爬取任务已启动，调度: ${cronExp}`);
    return true;
  }

  /**
   * 停止定时任务
   */
  stopSchedule() {
    if (this.task) {
      this.task.stop();
      this.task = null;
      console.log('定时爬取任务已停止');
      return true;
    } else {
      console.log('没有运行中的定时任务');
      return false;
    }
  }
}

module.exports = CrawlerScheduler; 